﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;


namespace WorldOfMUDra
{
    public partial class Player : ServerEngine.ServerClient
    {
        private string name;
        private Area location;
        private bool loggedIn = false;

        List<string> VisitedIDs = new List<string>();
        List<string> itemIDs = new List<string>();

        Dictionary<string, ServerCommandFunction> AbilityLibrary = new Dictionary<string, ServerCommandFunction>();
        Dictionary<string, ServerCommandFunction> gainedAbilities = new Dictionary<string, ServerCommandFunction>();

        Dictionary<string, IItem> Inventory = new Dictionary<string, IItem>();

        public Player(ServerEngine.Server host, Socket sock, string name) 
            : base(host, sock)
        {
            this.name = name;
            this.AddPlayerServerCommandActions();
        }

        public Player(ServerEngine.Server host, Socket sock)
            : base(host, sock)
        {
            this.name = "Guest";
            this.AddPlayerServerCommandActions();
        }

        private void AddPlayerServerCommandActions()
        {
            //this.ServerCommandActions.Add("whereami", new ServerCommandFunction(WhereAmICommand));
            this.ServerCommandActions.Add("login", new ServerCommandFunction(LogInCommand));
            //this.ServerCommandActions.Add("moveto", new ServerCommandFunction(MoveToCommand));
            this.ServerCommandActions.Add("say", new ServerCommandFunction(SayCommand));

            this.AbilityLibrary.Add("moveto", new ServerCommandFunction(MoveToCommand));
            this.AbilityLibrary.Add("whereami", new ServerCommandFunction(WhereAmICommand));
            this.AbilityLibrary.Add("lookaround", LookAroundCommand);
            this.AbilityLibrary.Add("lookat", LookAtCommand);
            this.AbilityLibrary.Add("inventory", InventoryCommand);
        }

        protected override void OnSocketClose()
        {
            Globals.CreateConfigFor(this);
        }

        /// <summary>
        /// Sends a list of inventory items to the client to be displayed however the client deems best.
        /// </summary>
        public void SendInventory()
        {
            string list = "";
            foreach (IItem item in this.Inventory.Values)
            {
                list += item.ID + " " + item.Name + " ";
            }
            this.SendRawMessage(ServerEngine.MudraProtocol.Inventory.ToString("d") + list);
        }

        /// <summary>
        /// Tell the client to play a certain sound file, if the file exists.
        /// </summary>
        /// <param name="SoundName">The name of the sound file to be played. DO NOT append a file extension (ie .mp3, .wav, etc).</param>
        /// <param name="Loop">Whether the sound should be loop or not.</param>
        public void PlaySound(string SoundName, bool Loop)
        {
            string l = "0";
            if (Loop) l = "1";
            this.SendRawMessage(ServerEngine.MudraProtocol.Sound.ToString("d") + " " + SoundName + " " + l);
        }

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        public bool LoggedIn
        {
            get { return loggedIn; }
        }

        public string Location
        {
            get { return location.Description; }
        }

        public string LocationID
        {
            get { return location.ID; }
        }

        new public void SendChatMessage(string msg)
        {
            if (msg != null) SendRawMessage(ServerEngine.MudraProtocol.Chat.ToString("d") + " Someone " + msg);
        }

        public void SendChatMessage(string sender, string msg)
        {
            if (msg != null) SendRawMessage(ServerEngine.MudraProtocol.Chat.ToString("d") + " " + sender + " " + msg);
        }

        public void WarpTo(Area area)
        {
            area.MoveHere(this);
        }

        public void MoveTo(string DestinationName)
        {
            if (this.location.LeadsTo(DestinationName))
            {
                this.location = this.location.Places(DestinationName);
            }
        }

        public void MoveTo(Area Destination)
        {
            this.location = Destination;
        }

        public Area CurrentArea()
        {
            return this.location;
        }

        public void AddVisitedArea(PlayerConfigFile pcf)
        {
            if (pcf.VisitedAreas != null)
            {
                foreach (string AID in pcf.VisitedAreas)
                {
                    Console.WriteLine("Adding area ID '"+AID.Trim()+"' from config.");
                    this.VisitedIDs.Add(AID.Trim());
                }
                foreach (string id in pcf.ItemIDs) this.itemIDs.Add(id);
            }
        }

        public void AddVisitedArea(string area)
        {
            if (!this.VisitedIDs.Contains(area.Trim())) this.VisitedIDs.Add(area);
        }

        public string VisitedAreas
        {
            get
            {
                return string.Join(" ", this.VisitedIDs);
            }
        }

        public string ItemIDs
        {
            get
            {
                return string.Join(" ", this.itemIDs);
            }
        }

        public string GainedAbilities
        {
            get
            {
                return string.Join(" ", this.gainedAbilities.Keys);
            }
        }

        public bool HasVisited(Area a)
        {
            Console.WriteLine("Checking to see if "+this.name+" has '"+a.ID+"'");
            return this.VisitedIDs.Contains(a.ID);
        }

        public bool HasPickedUp(IItem i)
        {
            return this.itemIDs.Contains(i.ID);
        }

        public void GiveAbility(ServerCommandFunction ability, string name, string desc, string syntax, string keyword)
        {
            if (!this.gainedAbilities.ContainsKey(keyword))
            {
                this.gainedAbilities.Add(keyword, ability);
                this.SendWorldMessage("You gained the ability: " + name + "! "+desc+"\nThe syntax is: "+syntax);
            }
            if (!this.ServerCommandActions.ContainsKey(keyword))
            {
                this.ServerCommandActions.Add(keyword, ability);
            }
        }

        public void LoadAbility(ServerCommandFunction ability, string keyword)
        {
            this.gainedAbilities.Add(keyword, ability);
            this.ServerCommandActions.Add(keyword, ability);
        }

        public void LoadAbilities(PlayerConfigFile pcf)
        {
            foreach (string ability in pcf.Abilities)
            {
                if (this.AbilityLibrary.ContainsKey(ability)) this.LoadAbility(this.AbilityLibrary[ability], ability);
            }
        }
    }
}
